# -*- coding: utf-8 -*-
#===============================================================================
# Koro Business Environment
# Copyright (C) 2010  Antonio Corroppoli
#
#This file is part of Koro BE.
# 
# Koro BE is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Koro BE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Koro BE; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#===============================================================================
import os
import wx
from koro.core import exception
from koro.ui.wxgui.widgets import controls as co,dialogs
#from koro import PDF_VIEWER
from koro.ui.wxgui.mellcfg import FONT_SIZE,SHOW_ID
from koro.ui.wxgui.widgets.controls import KoroPageToolBar
from koro.ui.wxgui.panels import ContextManager  
#from koro.ui.wxgui.clienti import ClientiPage, FornitoriPage
#from koro.ui.wxgui.iva import CodiciIvaPage
#from koro.ui.wxgui.prodotti import  ProdottiPage,CategorieProdottiPage
#from koro.ui.wxgui.listini import ListiniPage
#from koro.ui.wxgui.ordini import OrdiniFornitoreListPage,OrdiniClienteListPage,VenditeBancoListPage,FattureListPage,ArriviMerceListPage,RegistrazioniListPage
#from koro.ui.wxgui.magazzino import MovimentiMagazzinoPage,InventarioPage
#from koro.ui.wxgui.documenti import FatturePage
##from koro.ui.wxgui.agenda import AgendaPage
#from koro.ui.wxgui.opzioni import OpzioniPage
#from koro.ui.wxgui.home import HomePage 


#===============================================================================
# AbstractPage
#===============================================================================
class AbstractPage(object):
    
    def get_selection(self):
        """Usato dalle tabelle(Table()).Restituisce i dati selezionati.
        
        OVERRIDE IN SUBCLASS IF NECESSARY!!!"""        
        pass
    
    def before_save(self):
        '''Metodo chiamato prima del salvataggio di un oggetto.
        
        OVERRIDE IN SUBCLASS IF NECESSARY!!!'''
        return True
    
    def after_save(self):
        '''Metodo chiamato dopo il salvataggio di un oggetto.
        
        OVERRIDE IN SUBCLASS IF NECESSARY!!!'''
        pass
    
    def before_delete(self):
        '''Metodo chiamato prima dela cancellazione di un oggetto.Returns bool.
        
        OVERRIDE IN SUBCLASS IF NECESSARY!!!'''
        return True
    
    def after_delete(self):
        '''Metodo chiamato dopo la cancellazione di un oggetto.
        
        OVERRIDE IN SUBCLASS IF NECESSARY!!!'''
        pass

    def on_page_focus(self):
        '''Metodo chiamato quando la pagina riceve il focus. Solo nella versione notebook.
        
        OVERRIDE IN SUBCLASS IF NECESSARY!!!'''
        pass
    
    def on_kill_page_focus(self):
        '''Metodo chiamato quando la pagina perde il focus. Solo nella versione notebook.
        
        OVERRIDE IN SUBCLASS IF NECESSARY!!!'''
        pass
    
    def before_close(self):
        '''Metodo chiamato prima che una pagina venga chiusa.
        
        OVERRIDE IN SUBCLASS IF NECESSARY!!!'''
        pass


#===============================================================================
# TablePage
#===============================================================================
class TablePage(wx.Panel):
    TITLE=''
    def __init__(self,*args,**kwargs):
        wx.Panel.__init__(self,wx.GetApp().get_main_frame())
        self._panel=self._get_panel(*args,**kwargs)
        self._dialog=None
        self._dialog_size=wx.DefaultSize
    
    def _get_panel(self,*args,**kwargs):
        '''permette alle sottoclassi di definire il panel della tabella.'''
        pass
    
    def _set_dialog_size(self,size):
        self._dialog_size=size
    
    def show(self):
        self.dlg=dialogs.KoroDialog(self,title=self.TITLE,size=self._dialog_size,style=wx.CAPTION)
        self.dlg.set_panel(self._panel)#esegue reparent
        if self._dialog_size==wx.DefaultSize:
            self.dlg.fit()
        self._panel.init_page_view()
        self.dlg.show(False)
    
    def before_close(self):
        self._panel.before_close()
        self.dlg.Close()
        self.dlg.Destroy()
    
    def reset_focus(self):
        self._panel.reset_focus()        


PAGE_DEFAULT_STYLE=wx.NO_BORDER|wx.CLIP_CHILDREN|wx.TAB_TRAVERSAL
#===============================================================================
# BasePage
#===============================================================================
class BasePage(wx.Panel,ContextManager,AbstractPage):
    '''Classe base di tutte le pagine che hanno bisogno delle tre funzioni di base (Nuovo,Salva,Elimina).
    Di default usa il sizer wxBoxSizer(wx.VERTICAL) e DefaultToolBar.'''
    NORMAL_STATE=0
    NEW_STATE=1
    EDIT_STATE=2
    def __init__(self,parent,context,objects_list,style=PAGE_DEFAULT_STYLE,toolbar=True,*args,**kwargs):
        wx.Panel.__init__(self,parent,style=style,*args,**kwargs)
        ContextManager.__init__(self)
        self.SetExtraStyle(wx.WS_EX_VALIDATE_RECURSIVELY)
        #self.SetBackgroundColour("#BACAD0")        
        self.list_manager=co.KoroListCtrlManager()
        self.list_manager.set_managed_list(co.KoroListCtrl(self))
        self.list_manager.bind_callback(wx.EVT_LIST_ITEM_DESELECTED, self._item_deselected_callback)
        self.list_manager.bind_callback(wx.EVT_LIST_ITEM_SELECTED,self.view_object)
        self.SetSizer(self._get_default_topsizer())
        self._tb=None
        if toolbar:
            self._create_toolbar()        
        #self._item_selected=-1
        self.set_context_class(context)
        self._page_state=BasePage.NORMAL_STATE
        #self._action_map={}
        #self._objects_list=objects_list
    
    def _item_deselected_callback(self,obj,index):
        if self._page_state==BasePage.NEW_STATE:
            return#se mi trovo in NEW_STATE l'oggetto deselezionato è stato già processato
        try:
            self._process_object(obj)
            self.list_manager.refresh_item(index)
        except exception.KoroIntegrityError:
            wx.GetApp().show_error('Operazione non consentita!')        
    
    def before_close(self):
        self._process_current_object()
#        observer=wx.GetApp().get_observer()
#        observer.notify_page_closing()
    def _process_current_object(self):
        obj=self.list_manager.get_selected_object()
        self._process_object(obj)
    
    def _process_object(self,obj):
        #if self._page_state != BasePage.NORMAL_STATE and \
        if obj is not None:
            self.update_object(obj)
            self._get_page_observer().autosave_object(obj)
            #self.set_normal_state()
    
    def init_page_view(self):
        self.list_manager.set_focus()
        self.list_manager.select(0)
        #self.view_object(self.list_manager.get_selected_object(),0)
        #self.show()
    
    def show(self):
        self.init_page_view()
        self.Reparent(wx.GetApp().main_frame())
    
    def set_list_columns(self,*args):
        self.list_manager.set_columns(args)
    
    def load_list_objects(self,objects):
        self.list_manager.load(objects)
        if not objects:
            self.enable_page(False)
    
    def set_page_state(self,page_state):
        self._page_state=page_state
        self._update_toolbar(page_state)
    
    def _update_toolbar(self,page_state):
        show=page_state == BasePage.NORMAL_STATE        
        self._tb.show_tool(wx.ID_SAVE,not show,1)
        
    
    def _get_default_topsizer(self):
        '''Restituisce il Sizer da usare come sizer principale della pagina.
        Di default restituisce un BoxSizer(wx.VERTICAL). Ridefinire questo 
        metodo nella sottoclasse per usare un altro Sizer.'''          
        return wx.BoxSizer(wx.VERTICAL)
        
    def _create_toolbar(self):
        '''Imposta la toolbar e la aggiunge al Sizer principale. 
        Di default usa KoroPageToolBar.
        NOTA: Questo metodo non funziona se il Sizer non è un BoxSizer. In tal caso ridefinire il metodo.'''
        self.set_toolbar(KoroPageToolBar(self))
        self.Sizer.Add(self.get_toolbar(),0,wx.EXPAND)        
        self.Sizer.Add(wx.StaticLine(self),0,wx.EXPAND|wx.TOP,border=3)
        self._tb.Bind(wx.EVT_TOOL,self._on_action_new,id=wx.ID_NEW)
        self._tb.Bind(wx.EVT_TOOL,self._on_action_save,id=wx.ID_SAVE)
        self._tb.Bind(wx.EVT_TOOL,self._on_action_delete,id=wx.ID_DELETE)
        #self._tb.SetAcceleratorTable(wx.AcceleratorTable([(wx.ACCEL_NORMAL,wx.WXK_F2,wx.ID_NEW)]))
#        self.set_accelerator_table([(wx.ACCEL_NORMAL,wx.WXK_F2,wx.ID_NEW)])
    
    def view_object(self,obj,index):
        '''Visualizza nella maschera i campi dell'oggetto chiamando update_fields.
        Se obj è None resetta i campi della pagina. 
        E' una funzione di callback, viene chiamata dal list_manager dopo l'evento ITEM_SELECTED(tramite CallAfter).'''
        if obj is None:
            self.reset_fields()
        else:
            self.update_fields(obj)

    def get_title(self):
        return self.TITLE#VARIABILE DI CLASSE
    
    def aggiorna_totali(self,dataObj):
        '''Non centra nulla qui'''
        dataObj.calcola_totali()
        self.totali.set_totale_imponibile(dataObj.totale_imponibile)
        self.totali.set_totale_iva(dataObj.totale_iva)
        self.totali.set_totale(dataObj.get_totale())
        self.Layout()
        
    def _on_action_new(self,evt):
        '''Handler dell'evento wx.EVT_TOOL con id wx.ID_NEW.'''
        print self.__class__.__name__,"._on_action_new"
        #busycursor=wx.BusyCursor()
        wx.BeginBusyCursor()
        evt.StopPropagation()
        try:
            #self.Freeze()
            self.process_new()
            #self.Thaw()
            evt.Skip(False)
        except Exception,err:
            print err
            #msgD = wx.MessageDialog(None,"Si e' verificato un errore: "+str(err),style=wx.OK|wx.ICON_ERROR)
            #msgD.ShowModal()
            #msgD.Destroy()
        finally:
            if self.IsFrozen():
                self.Thaw()
            #del busycursor
            if wx.IsBusy():
                wx.EndBusyCursor()
            #self.reset_focus()
        
    def _on_action_save(self,evt):
        print self.__class__.__name__,"._on_action_save"
        wx.BeginBusyCursor()
        evt.StopPropagation()
        try:
            print "Save"            
            if not self.Validate():
                evt.Skip(False)
                return            
            self.Freeze()
            if self.before_save():
                self.process_save()
                self.after_save()
            self.Thaw()            
            evt.Skip(False)
        except Exception,err:
            #msg="Aggiungere il messaggio d'errore(OnAction in panels.basepage)"
            print err
#            msgD = wx.MessageDialog(None,"Si e' verificato un errore: "+str(err),style=wx.OK|wx.ICON_ERROR)
#            msgD.ShowModal()
#            msgD.Destroy()
            #raise Exception(err)
        finally:
            if self.IsFrozen():
                self.Thaw()
            if wx.IsBusy():
                wx.EndBusyCursor()
            self.reset_focus()
        evt.StopPropagation()
        
    def _on_action_delete(self,evt):
        print self.__class__.__name__,"._on_action_delete"
        wx.BeginBusyCursor()
        try:
            print "ELIMINA"                
            self.Freeze()
            if self.before_delete():
                self.process_delete()
                self.after_delete()
            self.Thaw()
            evt.Skip(False)
        except exception.KoroInvalidObject,msg:
            wx.GetApp().show_message(msg)
        except Exception,err:
            print err
#            msgD = wx.MessageDialog(None,"Si e' verificato un errore: "+str(err),style=wx.OK|wx.ICON_ERROR)
#            msgD.ShowModal()
#            msgD.Destroy()
        finally:
            if self.IsFrozen():
                self.Thaw()
            if wx.IsBusy():
                wx.EndBusyCursor()
            self.reset_focus()
        evt.StopPropagation()
    
    def get_toolbar(self):
        return self._tb
    
    def get_selected_object(self):
        return self.list_manager.get_selected_object()
    
    def set_toolbar(self,tb):
        self._tb=tb
        self._tb.realize()
    
    def get_caption(self):#TODO:controllare che e' sta roba
        return self.__caption
    
    def _request_new_object(self):
        """Chiede all'observer una nuova istanza."""
        observer=self._get_page_observer()
        newObj=observer.new_object()
        return newObj
    
    def _request_objects(self):
        """Chiede all'observer tutti gli oggetti che la pagina visualizza."""
        observer=self._get_page_observer()
        obj_list=observer.get_objects()
        return obj_list 
    
    def update_object(self,obj):
        """Aggiorna l'oggetto con i valori immessi nei campi della pagina.
        
        OVERRIDE IN SUBCLASS!!!"""
        pass
    
    def enable_page(self,enable=True):
        '''OVERRIDE IN SUBCLASS!'''
        return
    
    def process_new(self):
        """Chiamato quando viene cliccato il tasto 'Nuovo'"""
        self.set_page_state(BasePage.NEW_STATE)
        self._tb.EnableTool(wx.ID_NEW,False)
        self.list_manager.enable_list(False)        
        observer=self._get_page_observer()
        new_object=observer.new_object()
        #TODO:add_object crea l'evento item deselected e lo mette in coda
        #Il problema è che l'evento viene processato solo dopo
        #che l'evento corrente(NEW) termina
        #quindi processo l'obj corrente prima di aggiungere il nuovo
        self._process_current_object()
        self.list_manager.add_object(new_object)
        #self.update_fields(new_object)        
        self.enable_page()
        self.reset_focus()
  
#    def _on_abort_new(self,evt):#mi sa che non viene mai chiamato...
#        raise Exception('BasePage.on_abort_new:chi mi chiama?')
#        self.process_delete()
#        self._tb.UnBind(wx.EVT_TOOL,id=wx.ID_ABORT,handler=self._on_abort_new)
#        self._tb.DeleteTool(wx.ID_ABORT)
#        self._tb.realize()
#        self.set_page_state(BasePage.NORMAL_STATE)
#        self.list_manager.enable_list()
        
    def reset_focus(self):
        '''Setta il focus sul primo controllo utile per l'inserimento di un nuovo dato. '''
        pass
        
    def process_save(self):
        """Metodo chiamato quando viene cliccato il pulsante Salva."""
        print self.__class__.__name__,'process_save'
                
        observer=self._get_page_observer()
        obj=self.list_manager.get_selected_object()
        if obj is None:
            wx.GetApp().show_message("Selezionare un oggetto.")
            return
        self.update_object(obj)
        observer.save_object(obj)
        self.set_page_state(BasePage.NORMAL_STATE)#questo
        self.list_manager.enable_list()#questo
        self.list_manager.refresh_selected()
        self._tb.EnableTool(wx.ID_NEW,True)#e questo sono set_normal_state...
        self.reset_focus()

    def process_delete(self):
        """Metodo chiamato quando viene cliccato il pulsante Elimina."""
        print self.__class__.__name__,'process_delete'        
        obj=self.list_manager.get_selected_object()
        if obj is None: 
            raise exception.KoroInvalidObject("Selezionare la voce da eliminare.")
            #wx.GetApp().show_message("Selezionare l'oggetto da eliminare.")
            #return
        if not obj.is_pending_object():
            response=wx.GetApp().show_question('Rimuovere la voce selezionata?')
            if response!=wx.ID_YES:            
                return
        observer=self._get_page_observer()
        observer.delete_object(obj)
        self.set_normal_state()
        
    def set_normal_state(self):
        self.set_page_state(BasePage.NORMAL_STATE)
        self.list_manager.enable_list()
        self._tb.EnableTool(wx.ID_NEW,True)          
    
    def update(self):
        """Ricarica tutti i dati della pagina.
        
        Chiama _request_objects(), carica la lista degli oggetti e seleziona l'elemento selezionato prima dell'aggiornamento.
        """
        print self.__class__.__name__,'update'
        obj_list=self._request_objects()
        if not obj_list:
            self.reset_fields()
        self.list_manager.load(obj_list)
        self.enable_page(len(obj_list)>0)
        self.list_manager.select(0)
        #self.view_object(self.list_manager.get_selected_object(),0)
    
    def update_fields(self,obj):
        """OVERRIDE IN SUBCLASS"""
        pass
    
    def reset_fields(self):
        """OVERRIDE IN SUBCLASS"""
        raise Exception('{0}:non ha il metodo reset_fields'.format(self.__class__.__name__))
    
    def set_accelerator_table(self,*args,**kwargs):
        self.SetAcceleratorTable(wx.AcceleratorTable(*args,**kwargs))

#    def _crea_pdf(self,evt):
#        '''non centra nulla qui'''       
#        print 'crea_pdf'
#        busycursor=wx.BusyCursor()
#        try:
#            obj=self.get_current_object()
#            if obj is None or not self._is_valid():
#                return
#            observer=self._get_page_observer()        
#            self.update_object(obj)        
#            output_path=observer.action_request("crea_pdf",obj)
#            if output_path is not None:
#                message='Creato il file {0}\nVisualizzare il documento?'.format(output_path)
#                response=wx.GetApp().show_question(message)
#                if response==wx.ID_YES:
#                    cmd='{0} {1} &'.format(PDF_VIEWER,output_path)
#                    os.system(cmd)
#            else:
#                wx.GetApp().show_error('Errore durante la creazione del file.')
#        except Exception,err:
#            print err
#            msgD = wx.MessageDialog(None,"Si e' verificato un errore: "+str(err),style=wx.OK|wx.ICON_ERROR)
#            msgD.ShowModal()
#            msgD.Destroy()
#        finally:
#            del busycursor

       
#===============================================================================
# ListPage
#===============================================================================
class ListPage(BasePage):
    def __init__(self,*args,**kwargs):
        BasePage.__init__(self,*args,**kwargs)
        self.list_manager.clear_callback()

    def show(self):
        self._layout()
        #self.init_page_view()
        return BasePage.show(self)
    
    def _layout(self):        
        pass
    
    def reset_fields(self):
        pass
        
#        self._action=None
#        self._action_map={}
        #tb=co.ListPageToolBar(self)
        #self.set_toolbar(tb)
    
    def _get_default_topsizer(self):
        return wx.GridBagSizer(0,0)        
    
    def _create_toolbar(self):
        pass
    
    
    def before_close(self):
        pass#non faccio niente prima di chiudere
    
    def enable_page(self,enable=True):
        self.list_manager.enable_list(enable)        
    
#    def bind_action(self,action,handler):
#        self._action_map[action]=handler
#    
#    def unbind_action(self,action):
#        del self._action_map[action]
#    
#    def process_action(self,*args):
#        if self._action not in self._action_map:
#            return
#        handler=self._action_map[self._action]
#        self._action=None
#        ret=handler(*args)
#        return ret
    
    def view_object(self,obj):#override di BasePage.view_object
        pass#non ci sono campi in cui visualizzare i dati
    
    def select_first(self):
        self.list_manager.select(0)
    
    def process_new(self):
        self.set_page_state(BasePage.NEW_STATE)
    
#    def _on_edit(self,evt):#non dovrebbe essere qui
#        if self.list_ctrl.GetFirstSelected()<0:
#            wx.GetApp().show_message('Selezionare un documento.')
#            return
#        self.mostra_documento(None)
    
    def _configure_toolbar(self):
        '''Configura la toolbar della pagina. 
        Puo' essere utile nel caso in cui le pagine abbiano toolbar differenti.'''
        pass
    
    def _configure_list(self):
        '''Configura la ListCtrl della pagina. 
        Utile nel caso in cui le pagine abbiano ListCtrl differenti.'''
        pass
    
#    def _mostra_documento(self,doc,panel):
#        pass
#    
#    def mostra_documento(self,evt):
#        raise 'override in subclass'
#    
#    def stampa(self,evt=None):
#        pass

    def _expire_object(self,obj):
        observer=self._get_page_observer()
        observer.expire_object(obj)
    
    def save_object(self,obj):
        print self.__class__.__name__,'save_object'
        if obj is None: 
            return
        wx.BeginBusyCursor()
        try:                        
            self.Freeze()
            if self.before_save():
                observer=self._get_page_observer()
                observer.save_object(obj)
                self.after_save()
            self.Thaw()
        except Exception,err:
            print err
            #wx.GetApp().show_error("Si e' verificato un errore: {0}".format(str(err)))
            raise exception.KoroDBOperationException('')
        finally:
            if self.IsFrozen():
                self.Thaw()
            wx.EndBusyCursor()

    def after_delete(self):
        self.update()
    
    def expunge_object(self,obj):
        observer=self._get_page_observer()
        observer.expunge_object(obj)
    
    def delete_object(self,obj):
        observer=self._get_page_observer()
        observer.delete_object(obj)
    
#    def after_save(self):
#        self.update()
    
    def _is_valid(self):#TODO: e' una prova per fa funzionare la stampa pdf. si puo' liminare
        return True
    
    def set_normal_state(self):
        self.set_page_state(BasePage.NORMAL_STATE)
        self.enable_page()
    
    def _update_toolbar(self,page_state):
        pass#qui non serve aggiornare la toolbar


#class ListPage_old(BasePage):
#    def __init__(self,*args,**kwargs):
#        BasePage.__init__(self,*args,**kwargs)
#        #self.SetSizer(wx.GridBagSizer(0,0))
#        self._action=None
#        self._action_map={}
#        #tb=co.ListPageToolBar(self)
#        #self.set_toolbar(tb)
#    
#    def _get_default_topsizer(self):
#        return wx.GridBagSizer(0,0)        
#    
#    def _create_toolbar(self):
#        tb=co.ListPageToolBar(self)
#        self.set_toolbar(tb)
#        self.GetSizer().Add(self.get_toolbar(),(0,0),flag=wx.EXPAND|wx.BOTTOM,border=3)        
#        #topsizer.Add(wx.StaticLine(self),0,wx.EXPAND|wx.TOP,border=3)
#        tb.Bind(wx.EVT_TOOL,self._on_action_new,id=wx.ID_NEW)
#        tb.Bind(wx.EVT_TOOL,self._on_edit,id=wx.ID_EDIT)
#        tb.Bind(wx.EVT_TOOL,self._on_action_delete,id=wx.ID_DELETE)
#        tb.Bind(wx.EVT_TOOL,self._crea_pdf,id=wx.ID_PRINT)
#    
#    def bind_action(self,action,handler):
#        self._action_map[action]=handler
#    
#    def unbind_action(self,action):
#        del self._action_map[action]
#    
#    def process_action(self,*args):
#        if self._action not in self._action_map:
#            return
#        handler=self._action_map[self._action]
#        self._action=None
#        ret=handler(*args)
#        return ret
#    
#    def _on_action_new(self,evt):
#        print self.__class__.__name__,"._on_action_new"
#        try:
#            self.process_new()
#            evt.Skip(False)
#        except Exception,err:
#            print err
#            wx.GetApp().show_error("Si e' verificato un errore: {0}".format(err))
#        evt.StopPropagation()
#    
#    def select_first(self):
#        self.list_ctrl.select(0)
#        
#    def process_new(self):
#        self._deselect()
#        self.mostra_documento(evt=None)
#    
#    def _on_edit(self,evt):
#        if self.list_ctrl.GetFirstSelected()<0:
#            wx.GetApp().show_message('Selezionare un documento.')
#            return
#        self.mostra_documento(None)
#    
#    def _init_toolbar(self):
#        '''Inizializza la toolbar della pagina. 
#        Puo' essere utile nel caso in cui le pagine abbiano toolbar differenti.'''
#        pass
#    
#    def _mostra_documento(self,doc,panel):
#        pass
#    
#    def mostra_documento(self,evt):
#        raise 'override in subclass'
#    
#    def stampa(self,evt=None):
#        pass
#    
#    def save_object(self,obj):
#        print self.__class__.__name__,'save_object'
#        if obj is None: 
#            return
#        busycursor=wx.BusyCursor()
#        try:                        
#            self.Freeze()
#            if self.before_save():
#                observer=self._get_page_observer()
#                observer.save_object(obj)
#                self.after_save()
#            self.Thaw()
#        except Exception,err:
#            print err
#            wx.GetApp().show_error("Si e' verificato un errore: {0}".format(str(err)))
#        finally:
#            if self.IsFrozen():
#                self.Thaw()
#            del busycursor
#
#    def after_delete(self):
#        self.update()
#    
#    def after_save(self):
#        self.update()
#    
#    def _is_valid(self):#TODO: e' una prova per fa funzionare la stampa pdf. si puo' liminare
#        return True




        